﻿using System;
using Bricks.Injecting;

namespace Motar.ServiceProcess
{

    /// <summary>
    /// 
    /// </summary>
    public abstract class ServiceBase<TBootstrapper> : System.ServiceProcess.ServiceBase where TBootstrapper : IBootstrapper
    {

        /// <summary>
        /// 
        /// </summary>
        private readonly Func<TBootstrapper> _bootstrapperFactory;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bootstrapperFactory"></param>
        protected ServiceBase(Func<TBootstrapper> bootstrapperFactory)
        {
            if (bootstrapperFactory == null)
            {
                throw new ArgumentNullException("bootstrapperFactory");
            }
            _bootstrapperFactory = bootstrapperFactory;
        }

        /// <summary>
        /// 
        /// </summary>
        protected Func<TBootstrapper> BootstrapperFactory
        {
            get { return _bootstrapperFactory; }
        }

        /// <summary>
        /// 
        /// </summary>
        protected TBootstrapper Bootstrapper { get; set; }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="args"></param>
        protected override void OnStart(string[] args)
        {
            Bootstrapper = ApplicationActivator.Run<TBootstrapper>(BootstrapperFactory, HandleException);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="exceptionToHandle"></param>
        protected abstract void HandleException(TBootstrapper bootstrapper, Exception exceptionToHandle);

        /// <summary>
        /// 
        /// </summary>
        protected override void OnStop()
        {
            Bootstrapper.Dispose();

            Bootstrapper = default(TBootstrapper);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="service"></param>
        /// <returns></returns>
        protected override object GetService(Type service)
        {
            return this.Using(service);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <returns></returns>
        protected virtual TService GetService<TService>()
        {
            return this.Using<TService>();
        }
    }
}
